#include <iostream>
#include <sstream>

#include <gloox/gloox.h>
#include <gloox/jid.h>
#include <gloox/client.h>
#include <gloox/connectionlistener.h>
#include <gloox/presence.h>
#include <gloox/loghandler.h>
#include <gloox/disco.h>
#include <gloox/mucroom.h>
#include <gloox/mucroomhandler.h>
#include <gloox/message.h>
#include <gloox/connectiontcpclient.h>
#include <gloox/connectionbosh.h>
#include <gloox/connectionhttpproxy.h>

using namespace std;
using namespace gloox;

string Say[] = {
	"Ronaldo, brilha muito no CUrintinas",
	"Olha o cracha",
	"Professor barata ataca novamente",
	"Everybody Lies",
	"What happenned, hapenned",
	"Javascript eh a melhor invencao depois do cachorro-quente",
	"Daqui a pouco vamos estar estourando champagne e dando risadas",
	"Vai ficar pronto quando estive pronto",
};

class JClient : public ConnectionListener, LogHandler, MUCRoomHandler
{
public:
  JClient() {
    readyToSend = false;
  }
  virtual ~JClient()
  {
    delete r;
    delete j;
  }

  void start(char *_jid, char *_passwd, char *_host, char *_room, int _delay) {
    stringstream msg;
    JID jid(_jid);
    j = new Client(jid, _passwd);
    j->registerConnectionListener(this);
    //j->registerPresenceHandler(this);
    if (_host && *_host != '\0') j->setServer(_host);
    j->logInstance().registerLogHandler(LogLevelDebug, LogAreaAll, this);
    j->disco()->setVersion("Jaboti", "2009v2");
    j->disco()->setIdentity("client", "bot");

#if 0
    if (_host && *_host != '\0') {
      ConnectionTCPClient* conn0 = new ConnectionTCPClient(j->logInstance(),
                                                           _host, 5280);
      ConnectionBOSH* conn1 = new ConnectionBOSH(j, conn0, j->logInstance(),
                                                 _host, _jid);
      j->setConnectionImpl( conn1 );
    }
#endif

    j->setPresence(Presence::Available, 0);
    
    JID nick(_room);
    r = new MUCRoom(j, nick, this, 0);
    srand(getpid());
    ConnectionError ce = ConnNoError;
    if (j->connect(false)) {
      int i = 0;
      while (ce == ConnNoError) {
	if (readyToSend) {
	  usleep(rand() % _delay); /* sleep at least _delay microseconds */
	  msg.str("");
	  msg << Say[i % 8 ] << " (" << i << ")";
	  r->send(msg.str());
	  i++;
	}
	ce = j->recv(1000);
      }
    }
    cerr << "recv() retornou: " << "(" << ce << ")"  << endl;
  }

  virtual void onConnect()
  {
    cout << "Conectado" << endl;
    r->join();
    r->getRoomInfo();
    r->getRoomItems();
    readyToSend = true;
  }

  virtual bool onTLSConnect(const CertInfo& info)
  {
    return true;
  }

  virtual void onDisconnect(ConnectionError e) {
    cout << "Desconectado: " << e << endl;
  }

  virtual void handleLog(LogLevel level,
			 LogArea area, const string& message)
  {
    cerr << "log: level: " << level << ", area: " << area << ": " <<  message.c_str() << endl;
  }

  virtual void handlePresence(Presence* presence)
  {
    cout << "presenca" << endl;
  }
  
  virtual void handleMUCParticipantPresence(MUCRoom* room, const MUCRoomParticipant participant, const Presence& presence )
  {
    if (presence.presence() == Presence::Available) {
      cout << "Presenca: " << participant.nick->resource() << " entrou na sala" << endl;
    } else if (presence.presence() == Presence::Unavailable) {
      cout << "Presenca: " << participant.nick->resource() << " saiu da sala" << endl;
    } else {
      cout << "Presenca: " << participant.nick->resource() << " estado " << presence.presence() << endl;
    }
  }
    
  virtual void handleMUCMessage(MUCRoom* room, const Message& msg, bool priv)
  {
    cout << "Mensagem de " << msg.from().resource() << " > " << msg.body() << endl;
  }
  
  virtual bool handleMUCRoomCreation(MUCRoom *room)
  {
    cout << "Criando a sala " << room->name() << endl;
    return true;
  }
  
  virtual void handleMUCSubject(MUCRoom *room, const string& nick, const string& subject)
  {
    cout << "Novo assunto na sala " << subject << endl;
  }
  
  virtual void handleMUCInviteDecline(MUCRoom *room, const JID& invitee, const string& reason)
  {
    cout << "Convite..." << endl;
  }
  
  virtual void handleMUCError(MUCRoom *room, StanzaError error)
  {
    cout << "Erro! " << error << endl;
  }
  
  virtual void handleMUCInfo(MUCRoom *room, int features, const string& name, const DataForm* infoForm )
  {
    cout << "Info" << endl;
  }

  virtual void handleMUCItems( MUCRoom * room, const Disco::ItemList& items )
  {
    cout << "Items" << endl;
  }
  
private:
  Client *j;
  MUCRoom *r;
  bool readyToSend;
};

int main(int argc, char *argv[])
{
  if (argc != 6) {
    cout << "Uso: " << argv[0] << " <jid> <password> <host> <room> <delay>" << endl;
    cout << "  <jid> login@dominio/recurso ou login@dominio ou dominio (anonimo)" << endl;
    cout << "  <password> senha do login ou entao \"\" para usuario anonimo" << endl;
    cout << "  <host> nome do servidor para conectar ou \"\" para usar o do jid" << endl;
    cout << "  <room> sala@dominio/nick para entrar na sala" << endl;
    cout << "  <delay> valor magico para atraso no envio de mensagens" << endl;
    cout << "Exemplo: " << endl << argv[0] << " chat.terra \"\" dsv-centos5-64.terra.com.br teste@conference.chat.terra/jaboti 10000" << endl;
    return 1;
  }
  JClient *jc = new JClient();
  jc->start(argv[1], argv[2], argv[3], argv[4], atoi(argv[5]));
  delete(jc);

  return 0;
}
